package com.reguang.aspect;

import java.util.Timer;
import java.util.TimerTask;

import javax.servlet.http.HttpServletRequest;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.reguang.annotation.RequestLimit;
import com.reguang.exception.RequestTimesException;
import com.reguang.utils.ObjectUtils;
import com.reguang.utils.RedisOperator;

import lombok.extern.slf4j.Slf4j;

/**
 * 
 * <p>Title: RequestTimesAop</p>
 * <p>Description: 访问切面类</p>
 * @author weibiao
 * @date 2019年12月27日
 */
@Aspect
@Component
@Slf4j
public class RequestTimesAop {

	@Autowired
	private RedisOperator redisOperator;

	// 切面范围
	@Before("within(@org.springframework.web.bind.annotation.RestController *) && @annotation(limit)")
	public void requestLimit(final JoinPoint joinPoint, RequestLimit limit) throws Exception {
		try {
			Object[] args = joinPoint.getArgs();
			HttpServletRequest request = null;
			for (int i = 0; i < args.length; i++) {
				if (args[i] instanceof HttpServletRequest) {
					request = (HttpServletRequest) args[i];
					break;
				}
			}
			if (request == null) {
				throw new Exception("方法中缺失HttpServletRequest参数");
			}
			String ip = request.getLocalAddr();
			String url = request.getRequestURL().toString();
			String key = "req_limit_".concat(url).concat(ip);
			if (ObjectUtils.isNull(redisOperator.get(key))) {
				redisOperator.set(key, new Integer("1").toString());
			} else {
				Integer times = Integer.parseInt(redisOperator.get(key)) + 1;
				redisOperator.set(key, times.toString());
			}
			Integer count = Integer.parseInt(redisOperator.get(key));
			if (count > 0) {
				// 创建一个定时器
				Timer timer = new Timer();
				timer.schedule(new TimerTask() {
					@Override
					public void run() {
						// 这个定时器设定在time规定的时间之后会执行上面的remove方法，也就是说在这个时间后它可以重新访问
						redisOperator.del(key);
					}
				}, limit.time());
			}
			if (count > limit.count()) {
				log.info("用户IP[" + ip + "]访问地址[" + url + "]超过了限定的次数[" + limit.count() + "]");
				throw new RequestTimesException();
			}
		} catch (Exception e) {
			log.error("发生异常", e);
			throw e;
		}
	}
}
